#include <stdio.h>
#include <kewinternal.h>

#define SOURCE_FILE_NAME "Continuation"

KewObject *kew_top_continuation;


METHOD(Result)
{
  /* Make sure this continuation is valid before taking it */
  if (kew_continuation_frame(receiver) == NULL) {
    results[0] = KewSend1(KewContinuationAlreadyTaken, "raise", receiver);
    return;
  }

  /* Remove any exception handlers that were added after this cont. */
  while (kew_top_exception_handler_frame != NULL
         && KEW_STACKED_ABOVE(kew_top_exception_handler_frame,
                              kew_continuation_frame(receiver))) {
    kew_handler_frame(kew_top_exception_handler_frame->exception) =
      kew_handler_frame(kew_top_exception_handler_frame->exception)->next;
    kew_top_exception_handler_frame =
      kew_top_exception_handler_frame->next_on_stack;
  }

  /* Invalidate any continuations that are nested inside this one */
  while (kew_top_continuation != NULL
         && KEW_STACKED_ABOVE(kew_continuation_frame(kew_top_continuation),
                              kew_continuation_frame(receiver))) {
    KewObject *next_continuation =
      kew_continuation_frame(kew_top_continuation)->next_continuation;
    kew_continuation_frame(kew_top_continuation) = NULL;
    kew_top_continuation = next_continuation;
  }

  /* Now, the top continuation is whatever comes after this one */
  kew_top_continuation = kew_continuation_frame(receiver)->next_continuation;

  /* Take the continuation */
  siglongjmp(kew_continuation_frame(receiver)->jump_buffer, (int)args[0]);
}


KewObjectType kew_continuation_type = {
  SOURCE_FILE_NAME, __LINE__,
  1,
  {
    {"hash", Kew__GenericHash, 0, 1},
    {"=", Kew__GenericEqual, 1, 1},
    {"result", Result, 1, 1},
    {NULL, NULL, 0, 0}
  }
};

void
Kew__InitContinuation(void)
{
  kew_top_continuation = NULL;
}


